﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit.Electric;
using YArchitech.Revit.Electric.Common;
using YArchitech.Revit.MEP.Command;
using YArchitech.Revit.MEP.Modeling;
using YArchitech.Revit.RevitExtension;
using HYElectricCommon;
using HYRElectric.WirePlace;

namespace YArchitech.Revit.MEP.Public
{
	public class EquipmentConnect
	{
		public static Wire CreateWire(UIDocument uiDoc, ElementId firstEquipmentId, ElementId secondEquipmentId, WiringType wiringType)
		{
			Wire result;
			try
			{
				Element elementById = uiDoc.Document.GetElementById(firstEquipmentId);
				Element elementById2 = uiDoc.Document.GetElementById(secondEquipmentId);
				List<LineType> list = new List<LineType>();
				list = new LineTypeXMLManage(AssistFunc.GetAppRootPath() + "\\Data\\ElectricalData\\ElectricalLinetype.xml").GetLineType();
				WireParameters wireParameters = new WireParameters();
				if (!EquipmentConnect.IsHasFile())
				{
					IList<Element> wireType = EquipmentConnect.GetWireType(uiDoc.Document);
					wireParameters.WireType = wireType[0].Name;
					wireParameters.LineType = list[0].Title;
					wireParameters.LayMode = "BC";
				}
				else
				{
					EquipmentConnect.GetwireParamValue(wireParameters, uiDoc.Document);
				}
				LineType lineType = new LineType();
				string lineType2 = wireParameters.LineType;
				foreach (LineType lineType3 in list)
				{
					if (lineType2 == lineType3.Title)
					{
						lineType = lineType3;
						break;
					}
				}
				WireType wireType2 = null;
				foreach (object obj in uiDoc.Document.Settings.ElectricalSetting.WireTypes)
				{
					WireType wireType3 = (WireType)obj;
					if (wireType3.Name.Equals(wireParameters.WireType))
					{
						wireType2 = wireType3;
						break;
					}
				}
				Connector deviceConnector = EquipmentConnect.GetDeviceConnector(elementById);
				Connector deviceConnector2 = EquipmentConnect.GetDeviceConnector(elementById2);
				Line line = YJKLineEx.YJKGetBound(deviceConnector.Origin, deviceConnector2.Origin);
				Wire wire;
                if (wiringType == (WiringType)1)
				{
					List<XYZ> list2 = new List<XYZ>();
					list2.Add(deviceConnector.Origin);
					list2.Add(deviceConnector2.Origin);
                    wire = HyRevitUtils.CreateWire(uiDoc.Document, wireType2, uiDoc.Document.ActiveView, (Autodesk.Revit.DB.Electrical.WiringType)1, list2, deviceConnector, deviceConnector2);
				}
				else
				{
					wire = EquipmentConnect.CreateWireArc(uiDoc, wireType2, deviceConnector, deviceConnector2, line.Length);
				}
				EquipmentConnect.AssignParameters(wire, wireParameters, lineType, uiDoc);
				result = wire;
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		private static Wire CreateWireArc(UIDocument uiDoc, WireType wType, Connector connector1, Connector connector2, double lineLength)
		{
			XYZ xyz = (connector1.Origin + connector2.Origin) / 2.0;
			XYZ vect = connector1.Origin - xyz;
			double angle = EquipmentConnect.getAngle(connector1.Origin, connector2.Origin);
			XYZ xyz2;
			if ((angle >= 0.0 && angle < Math.PI*.5) || (angle >= 4.71238898038469 && angle < Math.PI*2))
			{
				xyz2 = EquipmentConnect.Rotate(vect, new XYZ(0.0, 0.0, 1.0), Math.PI*.5);
			}
			else
			{
				xyz2 = EquipmentConnect.Rotate(vect, new XYZ(0.0, 0.0, 1.0), -Math.PI*.5);
			}
			XYZ xyz3 = xyz + xyz2.Normalize() * (lineLength / 6.0);
			uiDoc.Application.Application.CreatYJKArc(new XYZ(connector1.Origin.X, connector1.Origin.Y, 0.0), new XYZ(connector2.Origin.X, connector2.Origin.Y, 0.0), new XYZ(xyz3.X, xyz3.Y, 0.0));
			List<XYZ> list = new List<XYZ>();
			list.Add(new XYZ(connector1.Origin.X, connector1.Origin.Y, 0.0));
			list.Add(new XYZ(xyz3.X, xyz3.Y, 0.0));
			list.Add(new XYZ(connector2.Origin.X, connector2.Origin.Y, 0.0));
			return HyRevitUtils.CreateWire(uiDoc.Document, wType, uiDoc.Document.ActiveView, 0, list, connector1, connector2);
		}

		private static double formatAngle(double angle)
		{
			int num = (int)(angle / Math.PI*2);
			double num2 = angle - (double)num * Math.PI*2;
			if (num2 < 0.0)
			{
				num2 += Math.PI*2;
			}
			return num2;
		}

		private static double getAngle(XYZ ptCenter, XYZ ptOut)
		{
			XYZ xyz = ptOut - ptCenter;
			return EquipmentConnect.formatAngle(XYZ.BasisX.AngleOnPlaneTo(xyz, XYZ.BasisZ));
		}

		private static bool IsHasFile()
		{
			return File.Exists(Path.GetTempPath() + "WireParamForm.dat");
		}

		private static void GetwireParamValue(WireParameters wireParameters, Document doc)
		{
			FileStream fileStream = new FileStream(Path.GetTempPath() + "WireParamForm.dat", FileMode.Open);
			StreamReader streamReader = new StreamReader(fileStream);
			streamReader.BaseStream.Seek(0L, SeekOrigin.Begin);
			string text = streamReader.ReadLine();
			IEnumerator<Element> enumerator = EquipmentConnect.GetWireType(doc).GetEnumerator();
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.Name == text.Trim())
					{
						wireParameters.WireType = text;
						break;
					}
				}
			}
			text = streamReader.ReadLine();
			wireParameters.LineType = text;
			text = streamReader.ReadLine();
			wireParameters.WireHot = Convert.ToInt32(text);
			text = streamReader.ReadLine();
			wireParameters.WireGround = Convert.ToInt32(text);
			text = streamReader.ReadLine();
			wireParameters.WireNeutral = Convert.ToInt32(text);
			text = streamReader.ReadLine();
			wireParameters.HotWireCrossSection = Convert.ToDouble(text);
			text = streamReader.ReadLine();
			wireParameters.WireCrossSection = Convert.ToDouble(text);
			text = streamReader.ReadLine();
			wireParameters.LayMode = text;
			streamReader.Close();
			fileStream.Close();
		}

		public static XYZ Rotate(XYZ vect, XYZ axis, double angle)
		{
			double x = axis.X;
			double y = axis.Y;
			double z = axis.Z;
			double[,] array = new double[3, 3];
			array[0, 0] = x * x;
			array[0, 1] = x * y;
			array[0, 2] = x * z;
			array[1, 0] = y * x;
			array[1, 1] = y * y;
			array[1, 2] = y * z;
			array[2, 0] = z * x;
			array[2, 1] = z * y;
			array[2, 2] = z * z;
			double[,] array2 = array;
			double[,] array3 = new double[3, 3];
			array3[0, 1] = -z;
			array3[0, 2] = y;
			array3[1, 0] = z;
			array3[1, 2] = -x;
			array3[2, 0] = -y;
			array3[2, 1] = x;
			double[,] array4 = array3;
			double[,] array5 = new double[3, 3];
			array5[0, 0] = 1.0 - array2[0, 0];
			array5[0, 1] = -array2[0, 1];
			array5[0, 2] = -array2[0, 2];
			array5[1, 0] = -array2[1, 0];
			array5[1, 1] = 1.0 - array2[1, 1];
			array5[1, 2] = -array2[1, 2];
			array5[2, 0] = -array2[2, 0];
			array5[2, 1] = -array2[2, 1];
			array5[2, 2] = 1.0 - array2[2, 2];
			double[,] array6 = array5;
			double[,] array7 = new double[3, 3];
			array7[0, 0] = array2[0, 0] + Math.Cos(angle) * array6[0, 0] + Math.Sin(angle) * array4[0, 0];
			array7[0, 1] = array2[0, 1] + Math.Cos(angle) * array6[0, 1] + Math.Sin(angle) * array4[0, 1];
			array7[0, 2] = array2[0, 2] + Math.Cos(angle) * array6[0, 2] + Math.Sin(angle) * array4[0, 2];
			array7[1, 0] = array2[1, 0] + Math.Cos(angle) * array6[1, 0] + Math.Sin(angle) * array4[1, 0];
			array7[1, 1] = array2[1, 1] + Math.Cos(angle) * array6[1, 1] + Math.Sin(angle) * array4[1, 1];
			array7[1, 2] = array2[1, 2] + Math.Cos(angle) * array6[1, 2] + Math.Sin(angle) * array4[1, 2];
			array7[2, 0] = array2[2, 0] + Math.Cos(angle) * array6[2, 0] + Math.Sin(angle) * array4[2, 0];
			array7[2, 1] = array2[2, 1] + Math.Cos(angle) * array6[2, 1] + Math.Sin(angle) * array4[2, 1];
			array7[2, 2] = array2[2, 2] + Math.Cos(angle) * array6[2, 2] + Math.Sin(angle) * array4[2, 2];
			double[,] array8 = array7;
			return new XYZ(array8[0, 0] * vect.X + array8[0, 1] * vect.Y + array8[0, 2] * vect.Z, array8[1, 0] * vect.X + array8[1, 1] * vect.Y + array8[1, 2] * vect.Z, array8[2, 0] * vect.X + array8[2, 1] * vect.Y + array8[2, 2] * vect.Z);
		}

		public static void CreateWireBySelection(UIDocument uiDoc, WireParamForm dlgConnect)
		{
			Document document = uiDoc.Document;
			Selection selection = uiDoc.Selection;
			bool flag = true;
			Element element = null;
			Element element2 = null;
			try
			{
				for (;;)
				{
					if (flag)
					{
						try
						{
							EquipmentConnect.isFirstEquipment = false;
							Reference reference = selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "请选择要连线的第一个设备");
							element = document.GetElement(reference);
						}
						catch (Exception)
						{
							EquipmentConnect.isFirstEquipment = true;
							throw;
						}
						Reference reference2 = selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "请选择要连线的设备");
						element2 = document.GetElement(reference2);
						flag = false;
					}
					else
					{
						element = element2;
						Reference reference3 = selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "请选择要连线的设备");
						element2 = document.GetElement(reference3);
					}
					if (element.Id == element2.Id)
					{
						MessageBox.Show("两次选择的为同一对象，请重新选择！", "盈建科提示");
					}
					else
					{
						EquipmentConnect.RemoveDuplicateConnection(document, element, element2);
						WireParameters wireParameters = dlgConnect.wireParameters;
						LineType lineType = new LineType();
						string lineType2 = wireParameters.LineType;
						foreach (LineType lineType3 in dlgConnect.lineTypeList)
						{
							if (lineType2 == lineType3.Title)
							{
								lineType = lineType3;
								break;
							}
						}
						WireType wireType = null;
						foreach (object obj in uiDoc.Document.Settings.ElectricalSetting.WireTypes)
						{
							WireType wireType2 = (WireType)obj;
							if (wireType2.Name.Equals(wireParameters.WireType))
							{
								wireType = wireType2;
								break;
							}
						}
						Connector deviceConnector = EquipmentConnect.GetDeviceConnector(element);
						Connector deviceConnector2 = EquipmentConnect.GetDeviceConnector(element2);
						Line line = YJKLineEx.YJKGetBound(deviceConnector.Origin, deviceConnector2.Origin);
						Wire wire;
						if (dlgConnect.cbxWire.SelectedIndex == 0)
						{
							List<XYZ> list = new List<XYZ>();
							list.Add(deviceConnector.Origin);
							list.Add(deviceConnector2.Origin);
                            wire = HyRevitUtils.CreateWire(uiDoc.Document, wireType, uiDoc.Document.ActiveView, (Autodesk.Revit.DB.Electrical.WiringType)1, list, deviceConnector, deviceConnector2);
						}
						else
						{
							wire = EquipmentConnect.CreateWireArc(uiDoc, wireType, deviceConnector, deviceConnector2, line.Length);
						}
						EquipmentConnect.AssignParameters(wire, wireParameters, lineType, uiDoc);
					}
				}
			}
			catch (Exception)
			{
				throw;
			}
		}

		private static void RemoveDuplicateConnection(Document doc, Element ele1, Element ele2)
		{
			foreach (Element element in EquipmentConnect.GetWire(doc))
			{
				Wire wire = element as Wire;
				List<Connector> list = new List<Connector>();
				List<ElementId> list2 = new List<ElementId>();
				ConnectorSetIterator connectorSetIterator = wire.ConnectorManager.Connectors.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					object obj = connectorSetIterator.Current;
					Connector item = obj as Connector;
					list.Add(item);
				}
				foreach (Connector connector in list)
				{
					ConnectorSet allRefs = connector.AllRefs;
					if (allRefs.Size > 0)
					{
						foreach (object obj2 in allRefs)
						{
							Element owner = ((Connector)obj2).Owner;
							if (owner is FamilyInstance && !list2.Contains(owner.Id))
							{
								list2.Add(owner.Id);
							}
						}
					}
				}
				bool flag = false;
				bool flag2 = false;
				using (List<ElementId>.Enumerator enumerator4 = list2.GetEnumerator())
				{
					while (enumerator4.MoveNext())
					{
						if (enumerator4.Current == ele1.Id)
						{
							flag = true;
							break;
						}
					}
				}
				using (List<ElementId>.Enumerator enumerator4 = list2.GetEnumerator())
				{
					while (enumerator4.MoveNext())
					{
						if (enumerator4.Current == ele2.Id)
						{
							flag2 = true;
							break;
						}
					}
				}
				if (flag && flag2)
				{
					doc.Delete(wire.Id);
					break;
				}
			}
		}

		public static Connector GetDeviceConnector(Element element)
		{
			Connector result = null;
			ConnectorSetIterator connectorSetIterator = (element as FamilyInstance).MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (connector.Domain == (Autodesk.Revit.DB.Domain)2)
				{
					result = connector;
					break;
				}
			}
			return result;
		}

		public static bool AssignParameters(Wire wire, WireParameters wireParam, LineType lineType, UIDocument uiDoc)
		{
			bool result;
			try
			{
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_TICKMARK_STATE).Set(2);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_HOT_ADJUSTMENT).Set(wireParam.WireHot);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_GROUND_ADJUSTMENT).Set(wireParam.WireGround);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_NEUTRAL_ADJUSTMENT).Set(wireParam.WireNeutral);
				EquipmentConnect.AddSharedParametersToWire(wire, wireParam, lineType, uiDoc.Document);
				result = true;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
				result = false;
			}
			return result;
		}

		public static void AddSharedParametersToWire(Wire wire, WireParameters wireParam, LineType lineType, Document doc)
		{
			Dictionary<string, ParameterType> dictionary = new Dictionary<string, ParameterType>();
            dictionary.Add("导线类型", (ParameterType)1);
            dictionary.Add("火线截面", (ParameterType)1);
            dictionary.Add("PE/N截面", (ParameterType)1);
            dictionary.Add("敷设方式", (ParameterType)1);
            dictionary.Add("线型名称", (ParameterType)1);
			Dictionary<string, ParameterType> dictionary2 = new Dictionary<string, ParameterType>();
            dictionary2.Add("线型", (ParameterType)1);
            dictionary2.Add("宽度", (ParameterType)1);
            dictionary2.Add("颜色", (ParameterType)2);
			foreach (KeyValuePair<string, ParameterType> keyValuePair in dictionary)
			{
				if (wire.GetParameter(keyValuePair.Key) == null)
				{
					SharedParameter.InsertSharedParameter(doc, BuiltInCategory.OST_Wire, "电气数据", dictionary, true);
					break;
				}
			}
			foreach (KeyValuePair<string, ParameterType> keyValuePair2 in dictionary2)
			{
				if (wire.GetParameter(keyValuePair2.Key) == null)
				{
					SharedParameter.InsertSharedParameter(doc, BuiltInCategory.OST_Wire, "电气数据", dictionary2, false);
					break;
				}
			}
			wire.GetParameter(dictionary.ElementAt(0).Key).Set(wireParam.WireType);
			wire.GetParameter(dictionary.ElementAt(1).Key).Set(wireParam.HotWireCrossSection.ToString());
			wire.GetParameter(dictionary.ElementAt(2).Key).Set(wireParam.WireCrossSection.ToString());
			wire.GetParameter(dictionary.ElementAt(3).Key).Set(wireParam.LayMode);
			wire.GetParameter(dictionary.ElementAt(4).Key).Set(lineType.Title);
			wire.GetParameter(dictionary2.ElementAt(0).Key).Set(lineType.Name);
			wire.GetParameter(dictionary2.ElementAt(1).Key).Set(lineType.Width.ToString());
			wire.GetParameter(dictionary2.ElementAt(2).Key).Set(lineType.Color);
		}

		public static IList<Element> GetWireType(Document doc)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(WireType)).ToElements();
		}

		public static IList<Element> GetWire(Document doc)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(Wire)).ToElements();
		}

		public static bool isFirstEquipment;
	}
}
